<template>
  <div class="file-viewer">
    <!-- 文件列表标题 -->
    <h1>文件列表</h1>
    <div class="file-list-container">
      <table class="file-list-table">
        <thead>
          <tr>
            <th>文件类型</th>
            <th>文件名</th>
            <th>操作</th>
          </tr>
        </thead>
        <tbody>
          <tr v-for="item in fileList" :key="item.filePath">
            <td>
              <i
                :class="{
                  'fas fa-folder': item.fileType === 'dir',
                  'fas fa-file': item.fileType === 'file'
                }"
              ></i>
            </td>
            <td>{{ item.fileName }}</td>
            <td>
              <button class="view-button" @click="handleView(item)">
                {{ item.fileType === 'dir' ? '进入' : '查看' }}
              </button>
            </td>
          </tr>
        </tbody>
      </table>
    </div>
    <!-- 文件内容标题 -->
    <h1>文件内容</h1>
    <div class="file-content-container">
      <!-- 根据状态显示不同内容 -->
      <div v-if="isLoading">加载中...</div>
      <div v-else-if="!fileContent">{{ defaultContent }}</div>
      <div v-else>
        <img v-if="isImage" :src="fileContent" alt="File Image" class="image-preview" />
        <pre v-else class="text-preview">{{ fileContent }}</pre>
      </div>
    </div>
  </div>
</template>

<script lang="ts" setup>
import { debounce } from 'lodash';
import { ref, onMounted, watch } from 'vue';
import { useRoute, useRouter } from 'vue-router';
import request from '../utils/request';

interface FileItem {
  fileName: string;
  filePath: string;
  fileType: 'dir' | 'file';
}

const route = useRoute();
const router = useRouter();
const fileList = ref<FileItem[]>([]);
const fileContent = ref<string>('');
const isImage = ref<boolean>(false);
const isLoading = ref<boolean>(false);
const defaultContent = ref<string>('请展示文件');

// 防抖获取文件列表
const debouncedFetchFileList = debounce(async (path = '') => {
  try {
    isLoading.value = true;
    const response = await request.get<FileItem[]>(`/api/files/${path}`,);
    fileList.value = response.data;
    // 进入新目录后清空文件内容
    fileContent.value = '';
    isImage.value = false;
  } catch (error) {
    console.error('获取文件列表失败:', error);
  } finally {
    isLoading.value = false;
  }
}, 300);

// 防抖获取文件详情
const debouncedFetchFileContent = debounce(async (path: string) => {
  try {
    isLoading.value = true;
    const response = await request.get(`/api/file/${path}`, { responseType: 'blob' });
    const contentType = response.headers['content-type'];
    if (contentType.startsWith('image')) {
      isImage.value = true;
      fileContent.value = URL.createObjectURL(response.data);
    } else {
      isImage.value = false;
      const reader = new FileReader();
      reader.onload = () => {
        fileContent.value = reader.result as string;
      };
      reader.readAsText(response.data);
    }
  } catch (error) {
    console.error('获取文件内容失败:', error);
  } finally {
    isLoading.value = false;
  }
}, 300);

// 处理查看按钮点击事件
const handleView = async (item: FileItem): Promise<void> => {
  if (item.fileType === 'dir') {
    try {
      await router.push(`/${item.filePath}`);
      await debouncedFetchFileList(item.filePath);
    } catch (error) {
      console.error('路由跳转或加载文件列表失败:', error);
    }
  } else {
    await debouncedFetchFileContent(item.filePath);
  }
};

// 处理路由变化
const handleRouteChange = async () => {
  let path = '';
  if (Array.isArray(route.params.path)) {
    path = route.params.path.join('/');
  } else if (typeof route.params.path === 'string') {
    path = route.params.path;
  }
  await debouncedFetchFileList(path);
  if (path) {
    const file = fileList.value.find((item) => item.filePath === path);
    if (file && file.fileType === 'file') {
      await debouncedFetchFileContent(path);
    }
  }
};

onMounted(handleRouteChange);
// 监听路由变化
watch(() => route.params.path, handleRouteChange, { deep: true });
</script>

<style scoped>
.file-viewer {
  display: flex;
  flex-direction: column;
  height: 100vh;
  padding: 20px;
}

h1 {
  color: #333;
  margin-bottom: 10px;
}

.file-list-container {
  flex: 1;
  overflow-y: auto;
  padding: 20px;
  background-color: #f5f5f5;
  border-radius: 8px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

.file-list-table {
  width: 100%;
  border-collapse: collapse;
}

.file-list-table th,
.file-list-table td {
  padding: 12px;
  text-align: left;
  border-bottom: 1px solid #ddd;
}

.file-list-table th {
  background-color: #4CAF50;
  color: white;
  border-top-left-radius: 8px;
  border-top-right-radius: 8px;
}

.view-button {
  background-color: #008CBA;
  border: none;
  color: white;
  padding: 8px 16px;
  text-align: center;
  text-decoration: none;
  display: inline-block;
  font-size: 14px;
  cursor: pointer;
  border-radius: 4px;
  transition: background-color 0.3s ease;
}

.view-button:hover {
  background-color: #005f73;
}

.file-content-container {
  flex: 1;
  overflow-y: auto;
  padding: 20px;
  background-color: #fff;
  border-radius: 8px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  margin-top: 20px;
}

.image-preview {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
}

.text-preview {
  white-space: pre-wrap;
  font-family: 'Courier New', Courier, monospace;
}
</style>